use std::fmt;

#[derive(Clone)]
pub struct Token{
pub token_type: TokenType,
    pub literal: String,
}

impl fmt::Debug for Token {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Token {{ token_type: {:?}, literal: '{}' }}", self.token_type, self.literal)
    }
}

impl Token{
    pub fn new(token_type: TokenType, ch: char) -> Self{
        Self{
            token_type: token_type,
            literal: ch.to_string(),
        }
    }
}

#[derive(Debug, Clone, Eq, Hash )]
pub enum TokenType{
    ILLEGAL,
    EOF,
    // 标识符+字面量
    IDENT, // add, foobar, x, y ...
    INT, //123454
    // 运算符
    ASSIGN,
    PLUS,
    MINUS,
    BANG,
    ASTERISK,
    SLASH,
    // 比较运算符
    LT,
    GT,
    EQ,
    NOT_EQ,
    // 分隔符
    COMMA,
    SEMICOLON,
    LPAREN,
    RPAREN,
    LBRACE,
    RBRACE,
    // 关键字
    FUNCTION,
    LET,
    TRUE,
    FALSE,
    IF,
    ELSE,
    RETURN,
}

impl TokenType{
    pub fn to_string(&self) -> String{
        match self {
            TokenType::ILLEGAL => String::from("ILLEGAL"),
            TokenType::EOF => String::from("EOF"),
            // 标识符+字面量
            TokenType::IDENT => String::from("IDENT"), // add, foobar, x, y ...
            TokenType::INT => String::from("INT"), //123454
            // 运算符
            TokenType::ASSIGN => String::from("="),
            TokenType::PLUS => String::from("+"),
            TokenType::MINUS => String::from("-"),
            TokenType::BANG => String::from("!"),
            TokenType::ASTERISK => String::from("*"),
            TokenType::SLASH => String::from("/"),
            // 比较运算符
            TokenType::LT => String::from("<"),
            TokenType::GT => String::from(">"),
            TokenType::EQ => String::from("=="),
            TokenType::NOT_EQ => String::from("!="),
            // 分隔符
            TokenType::COMMA => String::from(","),
            TokenType::SEMICOLON => String::from(";"),
            TokenType::LPAREN => String::from("("),
            TokenType::RPAREN => String::from(")"),
            TokenType::LBRACE => String::from("{"),
            TokenType::RBRACE => String::from("}"),
            // 关键字
            TokenType::FUNCTION => String::from("FUNCTION"),
            TokenType::LET => String::from("LET"),
            TokenType::TRUE => String::from("TRUE"),
            TokenType::FALSE => String::from("FALSE"),
            TokenType::IF => String::from("IF"),
            TokenType::ELSE => String::from("ELSE"),
            TokenType::RETURN => String::from("RETURN"),
        }
    }
}






// 通过关键字查找对应的类型
pub fn lookup_ident(ident: &str) -> TokenType{
    match ident{
        "fn" => TokenType::FUNCTION,
        "let" => TokenType::LET,
        "true" => TokenType::TRUE,
        "false" => TokenType::FALSE,
        "if" => TokenType::IF,
        "else" => TokenType::ELSE,
        "return" => TokenType::RETURN,
        _ => TokenType::IDENT,
    }
}

impl PartialEq for TokenType{
    fn eq(&self, other: &Self) -> bool {
        // self.token_type == other.token_type
        let mut result = false;
        match self {
            TokenType::ILLEGAL => {
                match other {
                    TokenType::ILLEGAL => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::EOF => {
                match other {
                    TokenType::EOF => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::IDENT => {
                match other {
                    TokenType::IDENT => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },

            TokenType::INT => {
                match other {
                    TokenType::INT => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::ASSIGN => {
                match other {
                    TokenType::ASSIGN => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::PLUS => {
                match other {
                    TokenType::PLUS => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::MINUS => {
                match other {
                    TokenType::MINUS => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::BANG => {
                match other {
                    TokenType::BANG => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::ASTERISK => {
                match other {
                    TokenType::ASTERISK => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::SLASH => {
                match other {
                    TokenType::SLASH => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::LT => {
                match other {
                    TokenType::LT => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::GT => {
                match other {
                    TokenType::GT => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::EQ => {
                match other {
                    TokenType::EQ => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::NOT_EQ => {
                match other {
                    TokenType::NOT_EQ => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::COMMA => {
                match other {
                    TokenType::COMMA => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::SEMICOLON => {
                match other {
                    TokenType::SEMICOLON => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::LPAREN => {
                match other {
                    TokenType::LPAREN => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::RPAREN => {
                match other {
                    TokenType::RPAREN => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::LBRACE => {
                match other {
                    TokenType::LBRACE => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::RBRACE => {
                match other {
                    TokenType::RBRACE => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::FUNCTION => {
                match other {
                    TokenType::FUNCTION => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::LET => {
                match other {
                    TokenType::LET => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::TRUE => {
                match other {
                    TokenType::TRUE => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::FALSE => {
                match other {
                    TokenType::FALSE => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::IF => {
                match other {
                    TokenType::IF => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::ELSE => {
                match other {
                    TokenType::ELSE => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            TokenType::RETURN => {
                match other {
                    TokenType::RETURN => {
                        result = true;
                    },
                    _ => {
                        result = false;
                    }
                }
            },
            // _ => {
            //     result = false;
            // }
        }
        // unimplemented!()
        result
    }    
}